/*
   Copyright (c) [Year] [name of copyright holder]
   [Software Name] is licensed under Mulan PSL v2.
   You can use this software according to the terms and conditions of the Mulan PSL v2. 
   You may obtain a copy of Mulan PSL v2 at:
            http://license.coscl.org.cn/MulanPSL2 
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
   See the Mulan PSL v2 for more details.  
*/

#ifndef JIAJIA_LINGINFO_HPP
#define JIAJIA_LINGINFO_HPP

namespace jiajia{

    // Msg 是整个 jiajia 编译器存储字符串信息的类
    // 后续若要添加信息字符串的话，请记得自行记录新添的字符串的 id
    // 如下使用规则:
    // typename Msg::idType xxMSG = Msg::Insert("我是一段字符串");

    struct Msg{
    public:
        using seqType = my::seq<string_t>;
        using idType = unsigned int;
        
        static seqType & en(){
            static seqType s(1024);
            static bool flag = true;

            if(flag){
                s.resize(0);
                s<<"empty string";
                flag = false;
            }

            return s;
        }

        static idType Insert(const string_t & str){
            en()<<str;
            return en().size()-1;
        }
        
        static bool Find(unsigned int n){
            return n < en().size();
        }

        static const string_t & Get(unsigned int n){
            my::assure(Find(n), "jiajia::MsgMap::Find 找不到序号 %d", n);
            return en()[n];
        }
    };

    using msg_t = typename Msg::idType;
    
    // LingInfo 是每条指令执行完之后的返回值，记录着执行过程中的信息
    // 在 jiajia 中包括运算符在内的所有调用都算是一条执行指令
    // 除了部分特殊执行，需要更改环境的指令无返回值，如 IF,IFFALSE,GOTO,此类语句
    // 这部分指令出错那就不是用户的错误了，而是编译器本身的错误。
    // 一些该指令的防出错的措施将在 ling.hpp 中说明

    class LingInfo{
    public:
        enum type{
            TYPE_BEGIN = 0,
            ERROR = TYPE_BEGIN, // ERROR 表示指令运行出错，打印报错信息，停止执行
            WARNING,            // WARRING 表示该指令的有隐藏的错误，比如类型转换,由配置控制是否打印信息
            OVERTIME,           // OVERTIME 表示该指令已经过时，打印建议信息
            DEBUG,              // DEBUG 表示该指令成功执行，但是依旧打印调用信息
            SUCCESS,            // SUCCESS 表示该指令成功执行，但是不打调用信息
            TYPE_END,
        };

        inline static bool CheckType(const unsigned char t){
            return t >= TYPE_BEGIN && t < TYPE_END;
        }
        
        LingInfo():
            mType(SUCCESS),
            mMsg(0)
            {}

        LingInfo(enum_t t, msg_t m):
            mType(t),
            mMsg(m)
            {}

        inline enum_t getType(){
            return mType;
        }

        inline const string_t & getStr(){
            return Msg::Get(mMsg);
        }

    private:
        enum_t mType;
        msg_t mMsg;
    };

    namespace notice{
        static const msg_t success = Msg::Insert("成功执行");
        static const msg_t unknown_err = Msg::Insert("发生了未知错误");
    }
}
#endif
